#ifndef _XX_YY_BMOCK_EXPECT_HPP
#define _XX_YY_BMOCK_EXPECT_HPP

#include "detail/bmock_test_mode_control.hpp"
#include "detail/bmock_fixture.hpp"
#include "detail/bmock_logfile.hpp"

#define __BMOCK_LOCATION\
	bmock::location(__FILE__,size_t(__LINE__))

#define __BMOCK_CONTROL(C)\
	bmock::test_mode_control C(__BMOCK_LOCATION,bmock::control_tools_ptr(new bmock::test_control_tools()))

#define __BMOCK_EXPECT_C(C,F)\
	{(C).set_void_result(__BMOCK_LOCATION);\
	F;\
	(C).validate_expect();\
	}

#define __BMOCK_EXPECT_RETURN_C(C,R,F)\
	{\
	bmock::result* p_res = bmock::make_value_result<decltype(F)>(R);\
	(C).set_result(__BMOCK_LOCATION, p_res);\
	F;\
	(C).validate_expect();\
	}

#define __BMOCK_EXPECT_THROW_C(C,E,F)\
	{(C).set_result(__BMOCK_LOCATION,bmock::create_exception(E));\
	try {\
		F;\
		(C).validate_expect();\
	} catch (const bmock::exception_result *) {} }


#define __BMOCK_STUB_C(C,F)\
	{(C).set_stub_recording_state();\
	(C).set_void_result(__BMOCK_LOCATION);\
	F;\
	(C).validate_expect();\
	}


#define __BMOCK_STUB_RETURN_C(C,R,F)\
	{\
	bmock::result* p_res = bmock::make_value_result<decltype(F)>(R);\
	(C).set_stub_recording_state();\
	(C).set_result(__BMOCK_LOCATION, p_res);\
	F;\
	(C).validate_expect();\
	}

#define __BMOCK_STUB_THROW_C(C,E,F)\
	{(C).set_stub_recording_state();\
	(C).set_result(__BMOCK_LOCATION,bmock::create_exception(E));\
	try {\
	F;\
	(C).validate_expect();\
	} catch (const bmock::exception_result *) {} }

#define __BMOCK_EXPECT_CALLBACK_C(C,CBK)\
	{(C).connect(CBK,__BMOCK_LOCATION); }

#define __BMOCK_VERIFY_C(C)\
	(C).verify(__BMOCK_LOCATION);

#define __BMOCK_REPLAY_C(C)\
	bmock::bmock_mutex::instance()->lock(); \
	bmock::bmock_logfile::instance()->add_to_log("Actual Test:"); \
	bmock::bmock_mutex::instance()->unlock(); \
	(C).replay(__BMOCK_LOCATION)

#define BMOCK_EXPECT(F)\
	__BMOCK_EXPECT_C(*bmock::test_mode_control::get_instance(),F)

#define BMOCK_EXPECT_RETURN(R,F)\
	__BMOCK_EXPECT_RETURN_C(*bmock::test_mode_control::get_instance(),R,F)

#define BMOCK_EXPECT_THROW(E,F)\
	__BMOCK_EXPECT_THROW_C(*bmock::test_mode_control::get_instance(),E,F)

#define BMOCK_STUB(F)\
	__BMOCK_STUB_C(*bmock::test_mode_control::get_instance(),F)

#define BMOCK_STUB_RETURN(R,F)\
	__BMOCK_STUB_RETURN_C(*bmock::test_mode_control::get_instance(),R,F)

#define BMOCK_STUB_THROW(E,F)\
	__BMOCK_STUB_THROW_C(*bmock::test_mode_control::get_instance(),E,F)


#define BMOCK_EXPECT_CALLBACK(CBK)\
	__BMOCK_EXPECT_CALLBACK_C(*bmock::test_mode_control::get_instance(),CBK)

#define BMOCK_VERIFY\
	__BMOCK_VERIFY_C(*bmock::test_mode_control::get_instance())

#define BMOCK_REPLAY\
	__BMOCK_REPLAY_C(*bmock::test_mode_control::get_instance())

#define __BMOCK_REPEAT_RANGE_C(C, CT_MIN, CT_MAX)\
	{(C).expect_call_range(CT_MIN, CT_MAX);}

#define BMOCK_REPEAT_RANGE(CT_MIN, CT_MAX)\
	__BMOCK_REPEAT_RANGE_C(*bmock::test_mode_control::get_instance(), CT_MIN, CT_MAX)

#define BMOCK_REPEAT_C(C, CT)\
	__BMOCK_REPEAT_RANGE_C(C, CT, CT)

#define BMOCK_REPEAT(CT)\
	BMOCK_REPEAT_C(*bmock::test_mode_control::get_instance(), CT)

#define BMOCK_INFINITE bmock::infinite_calls()

#define __BMOCK_NON_STRICT_C(C)\
	(C).add_mock_type(boost::shared_ptr<bmock::mocks_type>(new bmock::non_strict_mocks()));

#define BMOCK_NON_STRICT\
	__BMOCK_NON_STRICT_C(*bmock::test_mode_control::get_instance())

#define __BMOCK_STRICT_C(C)\
	(C).add_mock_type(boost::shared_ptr<bmock::mocks_type>(new bmock::strict_mocks()));

#define BMOCK_STRICT\
	__BMOCK_STRICT_C(*bmock::test_mode_control::get_instance())

#define __BMOCK_EXPECT_NON_STRICT_C(C, F)\
	{(C).set_non_strict_recording_state();\
	(C).set_void_result(__BMOCK_LOCATION);\
	F;\
	(C).validate_expect();\
	}

#define __BMOCK_EXPECT_RETURN_NON_STRICT_C(C,R,F)\
	{\
	bmock::result* p_res = bmock::make_value_result<decltype(F)>(R);\
	(C).set_non_strict_recording_state();\
	(C).set_result(__BMOCK_LOCATION,p_res);\
	F;\
	(C).validate_expect();\
	}

#define __BMOCK_EXPECT_THROW_NON_STRICT_C(C,E,F)\
	{(C).set_non_strict_recording_state();\
	(C).set_result(__BMOCK_LOCATION,bmock::create_exception(E));\
	try {\
	F;\
	(C).validate_expect();\
	} catch (const bmock::exception_result *) {} }

#define BMOCK_EXPECT_NON_STRICT(F)\
	__BMOCK_EXPECT_NON_STRICT_C(*bmock::test_mode_control::get_instance(), F)

#define BMOCK_EXPECT_RETURN_NON_STRICT(R,F)\
	__BMOCK_EXPECT_RETURN_NON_STRICT_C(*bmock::test_mode_control::get_instance(),R,F)

#define BMOCK_EXPECT_THROW_NON_STRICT(E,F)\
	__BMOCK_EXPECT_THROW_NON_STRICT_C(*bmock::test_mode_control::get_instance(),E,F)

#endif